package com.yaorange.certificate.service.impl;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.*;

import com.yaorange.certificate.domain.NjtCertificateCount;
import com.yaorange.certificate.domain.NjtUserPerfect;
import com.yaorange.certificate.mapper.NjtCertificateCountMapper;
import com.yaorange.certificate.mapper.NjtUserPerfectMapper;
import com.yaorange.certificate.vo.NjtCertificateVo;
import com.yaorange.common.config.RuoYiConfig;
import com.yaorange.common.core.domain.model.LoginUser;
import com.yaorange.common.enums.YesOrNoEnum;
import com.yaorange.common.exception.ServiceException;
import com.yaorange.common.utils.*;
import com.yaorange.common.utils.bean.BeanUtils;
import com.yaorange.common.utils.file.FileUtils;
import com.yaorange.system.service.ISysDictDataService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.math.NumberUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import com.yaorange.certificate.mapper.NjtCertificateMapper;
import com.yaorange.certificate.domain.NjtCertificate;
import com.yaorange.certificate.service.INjtCertificateService;
import org.springframework.transaction.annotation.Transactional;

import static com.sun.jna.platform.mac.IOReturnException.getCode;


/**
 * 合格证打印数据Service业务层处理
 *
 * @author coach tam
 * @date 2024-07-17
 */
@Service
@Slf4j
public class NjtCertificateServiceImpl implements INjtCertificateService
{
    public static final String NONGJT_CODE_PRE = "nongjt:code:";
    @Autowired
    private NjtCertificateMapper njtCertificateMapper;
    @Autowired
    private NjtCertificateCountMapper njtCertificateCountMapper;
    @Autowired
    private NjtUserPerfectMapper njtUserPerfectMapper;
    @Autowired
    private StringRedisTemplate stringRedisTemplate;
    @Autowired
    private  NjtCommonService commonService;
    //创建一个线程池(核心线程数4*2   最大线程数50   空闲线程存活时间1  单位时间分钟  队列容量50 拒绝策略(调用线程调用)  线程工厂 )
    private static final ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(4*2, 50, 1, TimeUnit.MINUTES, new ArrayBlockingQueue<>(50), new ThreadPoolExecutor.CallerRunsPolicy());

    /**
     * 查询合格证打印数据
     *
     * @param id 合格证打印数据主键
     * @return 合格证打印数据
     */
    @Override
    public NjtCertificate selectNjtCertificateById(Long id)
    {
        return njtCertificateMapper.selectNjtCertificateById(id);
    }

    /**
     * 查询合格证打印数据列表
     *
     * @param njtCertificate 合格证打印数据
     * @return 合格证打印数据
     */
    @Override
    @Transactional(readOnly = true)
    public List<NjtCertificateVo> selectNjtCertificateList(NjtCertificateVo njtCertificate)
    {
        commonService.getAuthNjtCertificate(njtCertificate);

        return njtCertificateMapper.selectNjtCertificateList(njtCertificate);
    }

    /**
     * 新增合格证打印数据
     *
     * @param njtCertificate 合格证打印数据
     * @return 结果
     */
    @Override
    public int insertNjtCertificate(NjtCertificate njtCertificate)
    {
        njtCertificate.setCreateTime(DateUtils.getNowDate());
        return njtCertificateMapper.insertNjtCertificate(njtCertificate);
    }

    /**
     * 修改合格证打印数据
     *
     * @param njtCertificate 合格证打印数据
     * @return 结果
     */
    @Override
    public int updateNjtCertificate(NjtCertificate njtCertificate)
    {
        njtCertificate.setUpdateTime(DateUtils.getNowDate());
        return njtCertificateMapper.updateNjtCertificate(njtCertificate);
    }

    /**
     * 批量删除合格证打印数据
     *
     * @param ids 需要删除的合格证打印数据主键
     * @return 结果
     */
    @Override
    public int deleteNjtCertificateByIds(Long[] ids)
    {
        return njtCertificateMapper.deleteNjtCertificateByIds(ids);
    }

    /**
     * 删除合格证打印数据信息
     *
     * @param id 合格证打印数据主键
     * @return 结果
     */
    @Override
    public int deleteNjtCertificateById(Long id)
    {
        return njtCertificateMapper.deleteNjtCertificateById(id);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public List<String> batchCode(NjtCertificate njtCertificate) {
        //校验打印数量
        Integer printNumber = njtCertificate.getPrintNumber();
        if (ObjectUtils.isEmpty(printNumber) || printNumber.equals(0)) {
            throw new ServiceException("打印数量不能为空");
        }
        //批量生成合格证编号
        List<String> result = new ArrayList<>();
        //1.新增合格证打印统计
        NjtCertificateCount njtCertificateCount = new NjtCertificateCount();
        njtCertificateCount.setCreateTime(DateUtils.getNowDate());
        BeanUtils.copyProperties(njtCertificate, njtCertificateCount);
        LoginUser loginUser = SecurityUtils.getLoginUser();
        NjtUserPerfect njtUserPerfect = njtUserPerfectMapper.selectNjtUserPerfectById(loginUser.getUserId());
        BeanUtils.copyProperties(njtUserPerfect, njtCertificateCount);
        njtCertificateCount.setCreateBy(loginUser.getUsername());
        njtCertificateCount.setCreateTime(DateUtils.getNowDate());
        njtCertificateCount.setPrintDate(njtCertificateCount.getCreateTime());
        njtCertificateCount.setUserId(loginUser.getUserId());

        njtCertificateCountMapper.insertNjtCertificateCount(njtCertificateCount);
        List<Future<NjtCertificate>> tasks = new ArrayList<>();
        //2.批量新增合格证详情
        for (int i = 0; i < printNumber; i++) {
            Future<NjtCertificate> task = threadPoolExecutor.submit(() -> {
                NjtCertificate tempCerti = new NjtCertificate();
                BeanUtils.copyProperties(njtCertificate, tempCerti);
                tempCerti.setCode(getCode(njtUserPerfect.getAddressCode()));
                String qrCodeUrl = createAndUploadQrCode(tempCerti.getCode());
                tempCerti.setQrcode(qrCodeUrl);
                tempCerti.setScanNum(0);
                tempCerti.setUserId(loginUser.getUserId());
                tempCerti.setSourceType(0);
                tempCerti.setCreateBy(loginUser.getUsername());
                tempCerti.setCreateTime(njtCertificateCount.getCreateTime());
                tempCerti.setDelFlag(YesOrNoEnum.YES.CODE);
                return tempCerti;
            });
            tasks.add(task);
        }
        //收集每个任务的返回值结果
        for (Future<NjtCertificate> task : tasks) {
            try {
                NjtCertificate certificate = task.get();
                result.add(certificate.getCode());
                njtCertificateMapper.insertNjtCertificate(certificate);
            } catch (Exception e) {
                log.error("异步创建合格证异常", e);
                throw new ServiceException("异步创建合格证异常");
            }
        }
        return result;
    }

    private String createAndUploadQrCode(String code) {
        //1.创建二维码
        String uploadPath = RuoYiConfig.getQrCodePath();
        String url = "http://42.193.49.238/scanCodeTrace?code=" + code;
        String fileName = code + ".jpg";
        QrCodeCreateUtil.doCreateQrCode(uploadPath, code, url, 400, true);
        //2.上传到七牛云
//        return "http://sgp6yair6.hn-bkt.clouddn.com/51010520240717000324.jpg";
        try {
            File dic = new File(uploadPath);
            if (!dic.exists()) {
                dic.mkdirs();
            }
            return QiniuUtils.upload(new FileInputStream(uploadPath + File.separator + fileName), fileName);
        } catch (FileNotFoundException e) {
            throw new ServiceException(e.getMessage());
        }
    }

    /**
     * 生成合格证编号
     * 地区码前6位+当前日期(yyyyMMdd)+6位自增(从1开始)
     * @param addressCode
     * @return
     */
    private String getCode(String addressCode) {
        if (StringUtils.isEmpty(addressCode)) {
            throw new ServiceException("当前用户地址码不能为空");
        }
        String addCodeStr = addressCode.substring(0, 6) ;
        String dateStr = DateUtils.dateTimeNow("yyyyMMdd");
        //判断redis中是否已经有今天打印数据,有就直接递增，没有就新增(初始值1)
        String redisKey = NONGJT_CODE_PRE + dateStr;
        Long code=1L;
        if (stringRedisTemplate.hasKey(redisKey)) {
            code = stringRedisTemplate.opsForValue().increment(redisKey);
        } else {
            Boolean b = stringRedisTemplate.opsForValue().setIfAbsent(redisKey, "1", 24, TimeUnit.HOURS);
            if (!b) {
                code = stringRedisTemplate.opsForValue().increment(redisKey);
            }
        }
        return addCodeStr+dateStr+String.format("%06d",code);
    }

    @Override
    public void batchSaveByCode(List<String> codeList) {
        if (CollectionUtils.isEmpty(codeList)) {
            throw new ServiceException("合格证编号不能为空");
        }
        njtCertificateMapper.batchSaveByCode(codeList);
    }

    @Override
    @Transactional(readOnly = true)
    public List<NjtCertificateVo> selectNjtCertificateAllList() {
        return njtCertificateMapper.selectNjtCertificateList(null);
    }

    @Override
    @Transactional
    public int selectTotalCount() {
        return njtCertificateMapper.selectTotalCount();
    }

    @Autowired
    private ISysDictDataService dictDataService;
    /**
     * 根据合格证编号查询
     *
     * @param code
     * @return
     */
    @Override
    @Transactional(readOnly = true)
    public NjtCertificate getByCode(String code) {
        NjtCertificateVo result = null;
        NjtCertificateVo query = new NjtCertificateVo();
        query.setCode(code);
        List<NjtCertificateVo> certificateList = njtCertificateMapper.selectNjtCertificateList(query);
        if (certificateList.isEmpty()) {
            return null;
        }

        result = certificateList.get(0);
        String produceType = result.getUserPerfect().getProduceType();
        if (null!=produceType){
            String typeName = dictDataService.selectDictLabel("produce_type", produceType);
            result.getUserPerfect().setProduceType(typeName);
        }
        return result;
    }
}
